#include "cameratestadaptor.h"
#include "errcode.h"
#include <QVariant>
#include <QFileInfo>

int CameraTestAdaptor::typeId = qRegisterMetaType<CameraTestAdaptor*>("CameraTestAdaptor*");

CameraTestAdaptor::CameraTestAdaptor()
{
    generateDBusObjectName();
    startDBusListener();
}

CameraTestAdaptor::~CameraTestAdaptor()
{
    releaseDBusObjectName();
}

int CameraTestAdaptor::GetStatus(QVariant &timeout, QVariant &LFSResult)
{
    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncGetInfo(m_hService, LFS_INF_CAM_STATUS, NULL, LFS_INDEFINITE_WAIT, m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    if (LFS_SUCCESS == hResult) {
        LPLFSCAMSTATUS pLFSCAMStatus = (LPLFSCAMSTATUS)pLFSResult->buffer;
        formatStatusInfo(pLFSCAMStatus, LFSResult);
    }
    else
        LFSResult.setValue((long)hResult);

    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

int CameraTestAdaptor::GetCapabilities(QVariant &timeout, QVariant &LFSResult)
{
    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncGetInfo(m_hService, LFS_INF_CAM_CAPABILITIES, NULL, LFS_INDEFINITE_WAIT, m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    if (LFS_SUCCESS == hResult) {
        LPLFSCAMCAPS pLFSCAMCaps = (LPLFSCAMCAPS)pLFSResult->buffer;
        formatCapabilitiesInfo(pLFSCAMCaps, LFSResult);
    }
    else
        LFSResult.setValue((long)hResult);

    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

int CameraTestAdaptor::TakePicture(QVariant &camera, QVariant &szPictureFile, QVariant &timeout, QVariant &LFSResult)
{
    if (camera.toString().isEmpty() || !camera.canConvert<int>())
        return ERR_PARAM;

    QFileInfo fileInfo(szPictureFile.toString());
    if (!fileInfo.isFile())
        return ERR_PARAM;

    if (timeout.toString().isEmpty() || !timeout.canConvert<int>())
        timeout.setValue((ulong)ULONG_MAX);

    LFSCAMTAKEPICTEX lfsCamTakePicture;
    memset(&lfsCamTakePicture, 0, sizeof(LFSCAMTAKEPICTEX));
    lfsCamTakePicture.camera = camera.toInt();
    lfsCamTakePicture.picture_file = szPictureFile.toString().toLocal8Bit().data();

    REQUESTID requestId = 0;
    HRESULT hResult = LFSAsyncExecute((HSERVICE)(m_hService), LFS_CMD_CAM_TAKE_PICTURE_EX, &lfsCamTakePicture, LFS_INDEFINITE_WAIT,
                                      m_szDBusObjectName, &requestId);
    if (LFS_SUCCESS != hResult)
        return ERR_INVOKE;

    LPLFSRESULT pLFSResult = NULL;
    if (!waitForResult(&pLFSResult, timeout.toInt()))
        return ERR_TIMEOUT;

    hResult = pLFSResult->result;
    LFSResult.setValue((long)hResult);
    FreeResult(pLFSResult);
    return hResult == LFS_SUCCESS ? ERR_OK : ERR_OTHER;
}

void CameraTestAdaptor::formatStatusInfo(LPLFSCAMSTATUS pLFSCAMStatus, QVariant& szLFSCAMStatus)
{
    DECLARE_STRINGSTREAM;

    BEGIN_GROUP;
    OUTPUT_NAME_VALUE("fwDevice", pLFSCAMStatus->device);
    BEGIN_GROUP_WITH_NAME("fwMedia");
    for (int i = 0; i < LFS_CAM_CAMERAS_SIZE; i++)
        OUTPUT_VALUE(pLFSCAMStatus->media[i]);
    END_GROUP;
    BEGIN_GROUP_WITH_NAME("fwCameras");
    for (int i = 0; i < LFS_CAM_CAMERAS_SIZE; i++)
        OUTPUT_VALUE(pLFSCAMStatus->cameras[i]);
    END_GROUP;
    BEGIN_GROUP_WITH_NAME("usPictures");
    for (int i = 0; i < LFS_CAM_CAMERAS_SIZE; i++)
        OUTPUT_VALUE(pLFSCAMStatus->pictures[i]);
    END_GROUP;
    if (pLFSCAMStatus->extra) {
        BEGIN_GROUP_WITH_NAME("lpszExtra");
        PARSE_EXTRAINFO(pLFSCAMStatus->extra);
        END_GROUP;
    }
    else
        OUTPUT_NAME_VALUE("lpszExtra", "(null)");
    OUTPUT_NAME_VALUE("wAntiFraudModule", pLFSCAMStatus->anti_fraud_module);
    END_GROUP;

    GET_STRINGSTREAM_DATA(szLFSCAMStatus);
}

void CameraTestAdaptor::formatCapabilitiesInfo(LPLFSCAMCAPS pLFSCAMCaps, QVariant &szLFSCAMCaps)
{
    DECLARE_STRINGSTREAM;

    BEGIN_GROUP;
    OUTPUT_NAME_VALUE("wClass", pLFSCAMCaps->dev_class);
    OUTPUT_NAME_VALUE("fwType", pLFSCAMCaps->dev_type);
    BEGIN_GROUP_WITH_NAME("fwCameras");
    for (int i = 0; i < LFS_CAM_CAMERAS_SIZE; i++)
        OUTPUT_VALUE(pLFSCAMCaps->cameras[i]);
    END_GROUP;
    OUTPUT_NAME_VALUE("usMaxPictures", pLFSCAMCaps->max_pictures);
    OUTPUT_NAME_VALUE("fwCamData", pLFSCAMCaps->cam_data);
    OUTPUT_NAME_VALUE("usMaxDataLength", pLFSCAMCaps->max_data_length);
    OUTPUT_NAME_VALUE("fwCharSupport", pLFSCAMCaps->char_support);
    if (pLFSCAMCaps->extra) {
        BEGIN_GROUP_WITH_NAME("lpszExtra");
        PARSE_EXTRAINFO(pLFSCAMCaps->extra);
        END_GROUP;
    }
    else
        OUTPUT_NAME_VALUE("lpszExtra", "(null)");
    OUTPUT_NAME_VALUE("bPictureFile", pLFSCAMCaps->picture_file);
    OUTPUT_NAME_VALUE("bAntiFraudModule", pLFSCAMCaps->anti_fraud_odule);
    if (pLFSCAMCaps->synchronizable_commands) {
        int i = 0;
        BEGIN_GROUP_WITH_NAME("lpdwSynchronizableCommands");
        do {
            OUTPUT_VALUE(pLFSCAMCaps->synchronizable_commands[i]);
        } while (pLFSCAMCaps->synchronizable_commands[++i] != 0);
        END_GROUP;
    }
    else
        OUTPUT_NAME_VALUE("lpdwSynchronizableCommands", "(null)");
    END_GROUP;
}
